/* $RCSFile: AddonNicePanesBase.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.Core/UI/WebControls/AddonNicePanesBase.cs $
 * $log$
 * Revision 19 2011/02/22 01:23:08  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 19 2011/02/22 01:22:15  christian.surieux
 *   V4 Migration 22/2/11
 * Revision 6 2010/08/06 19:56:29  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
using System.ComponentModel;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Globalization;

using AddonNice.UI.Design.WebControls;
using AddonNice.Diagnostics;
using AddonNice.Configuration;

using Trace2    =   System.Diagnostics.Trace;

namespace AddonNice.UI.WebControls
{
	#region Dedicated TraceSwitch 
	public class PanesTraceSwitch
	{
		static public ADNTraceSwitch	Sw	=	new ADNTraceSwitch("PanesTrace","Trace switch for Panes");
	}
	#endregion Dedicated TraceSwitch 

	/// <summary>
	/// AddonNicePanesBase class for supporting three pane browsing
	/// PortalModule controles are loaded into these panes according to database values readen when the portal is loaded
	/// This control must be added in any page that needs to load portalModules controls
	/// The DataBind on the page's elements triggers the loading of controls
	/// Beware that this DataBind must be made from the Page.PreInit Event, any DataBind sent after will not allow skins to be adapted (.Net 2)
	/// Default rendering for this control is a div containing a table
	/// Table columns range from 1 to 6 according parameters: content cells and separators
	/// Table has only one row
	/// Empty columns could be not created
	/// Each cell may contain a div named with its column's position
	/// Each cell is a container and has a style, content is defined declaratively and is also filled dynamically with modules according loaded pageID ( readen in portalsettings )
	/// </summary>
	[
	Designer("AddonNice.UI.Design.WebControls.AddonNicePanesDesigner")
	]
	public class AddonNicePanesBase : WebControl, INamingContainer, IAddonNicePane
	{
		#region Member variables
		
		bool _showFirstSeparator            =   true;
		bool _showLastSeparator             =   true;
		bool _showFirstHorizontalSeparator   =   true;
		bool _showLastHorizontalSeparator   =   true;

		private ArrayList[] innerDataSource;

		private TableStyle _tablePaneStyle;
		private TableItemStyle _leftPaneStyle;
		private TableItemStyle _contentPaneStyle;
		private TableItemStyle _rightPaneStyle;

		private Style _horizontalSeparatorStyle;
		private TableItemStyle _verticalSeparatorStyle;

		private ITemplate _leftPaneTemplate;
		private ITemplate _contentPaneTemplate;
		private ITemplate _rightPaneTemplate;
		private ITemplate _horizontalSeparatorTemplate;
		private ITemplate _verticalSeparatorTemplate;

		private Control _leftPaneContainer;
		private Control _contentPaneContainer;
		private Control _rightPaneContainer;
		private Control _verticalSeparatorContainer;
		private Control _horizontalSeparatorContainer;

		private System.Web.UI.WebControls.TableCell _leftPane;
		private System.Web.UI.WebControls.TableCell _contentPane;
		private System.Web.UI.WebControls.TableCell _rightPane;

		enum styleIndex : int
		{
			IDX_CONTROL_STYLE                 = 0,
			IDX_TABLE_STYLE                   = 1,
			IDX_LEFT_PANE_STYLE               = 2,
			IDX_CONTENT_PANE_STYLE            = 3,
			IDX_RIGHT_PANE_STYLE              = 4,
			IDX_HORIZONTAL_SEPARATOR_STYLE    = 5,
			IDX_VERTICAL_SEPARATOR_STYLE      = 6,
		}

		/// <summary>
		/// Left pane index
		/// </summary>
		protected const int IDX_LEFT_PANE_DATA = 0;
		/// <summary>
		/// Content pane index
		/// </summary>
		protected const int IDX_CONTENT_PANE_DATA = 1;
		/// <summary>
		/// Right pane index
		/// </summary>
		protected const int IDX_RIGHT_PANE_DATA = 2;
		#endregion

		bool _DefaultValues     =   true;
		/// <summary>
		/// Use Panels around table and inside each pane.
		/// </summary>
		[
		Bindable(true),
		Category("Features"),
		DefaultValue(true),
		Description("Set default minimal values.")
		]
		public bool DefaultValues 
		{
			get 
			{
				return _DefaultValues;
			}
			set 
			{
				_DefaultValues = value;
			}
		}

		bool _UsePanels =   true;
		/// <summary>
		/// Use Div around table and inside each pane.
		/// </summary>
		[
		Bindable(true),
		Category("Features"),
		DefaultValue(true),
		Description("Uses Panels to allow Ajax.Net.")
		]
		public bool UsePanels 
		{
			get 
			{
				return _UsePanels;
			}
			set 
			{
				_UsePanels = value;
			}
		}

		bool _DynamicPanes =   true;
		/// <summary>
		/// Uses Dynamic Panes which are only created when they contain something.
		/// </summary>
		[
		Bindable(true),
		Category("Features"),
		DefaultValue(true),
		Description("Uses Dynamic Panes which are only created when they contain something.")
		]
		public bool DynamicPanes 
		{
			get 
			{
				return _DynamicPanes;
			}
			set 
			{
				_DynamicPanes = value;
			}
		}

		/// <summary>
		/// Show First Vartical Separator.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue(true),
		Description("Show First Vertical Separator.")
		]
		public bool ShowFirstSeparator 
		{
			get 
			{
				return _showFirstSeparator;
			}
			set 
			{
				_showFirstSeparator = value;
			}
		}
		
		/// <summary>
		/// Show Last Vertical Separator.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue(true),
		Description("Show Last Vertical Separator.")
		]
		public bool ShowLastSeparator 
		{
			get 
			{
				return _showLastSeparator;
			}
			set 
			{
				_showLastSeparator = value;
			}
		}

		/// <summary>
		/// Show First Horizontal Separator.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue(true),
		Description("Show First Horizontal Separator.")
		]
		public bool ShowFirstHorizontalSeparator 
		{
			get 
			{
				return _showFirstHorizontalSeparator;
			}
			set 
			{
				_showFirstHorizontalSeparator = value;
			}
		}
		/// <summary>
		/// Show Last Horizontal Separator.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue(true),
		Description("Show last Horizontal Separator.")
		]
		public bool ShowLastHorizontalSeparator 
		{
			get 
			{
				return _showLastHorizontalSeparator;
			}
			set 
			{
				_showLastHorizontalSeparator = value;
			}
		}

		/// <summary>
		/// The width of the div.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue("100%"),
		Description("The width of the rendered table.")
		]
		public override Unit Width 
		{
			get 
			{
				if ( !ControlStyleCreated ) 
				{
					return 0;
				}
				return ControlStyle.Width;
			}
			set 
			{
				ControlStyle.Width = value;
			}
		}

		/// <summary>
		/// The height of the div.
		/// </summary>
		[
		Bindable(true),
		Category("Appearance"),
		DefaultValue(null),
		Description("The height of the rendered table.")
		]
		public override Unit Height 
		{
			get 
			{
				if ( !ControlStyleCreated ) 
				{
					return 0;
				}
				return ControlStyle.Height;
			}
			set 
			{
				ControlStyle.Height = value;
			}
		}

		// We Prefer a Div tag for the control
		protected override HtmlTextWriterTag TagKey
		{
			get
			{
				return HtmlTextWriterTag.Div;
			}
		}

				
		/// <summary>
		/// The style to be applied to table.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to Table."),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public TableStyle TablePaneStyle 
		{
			get 
			{
				if ( _tablePaneStyle == null) 
				{
					_tablePaneStyle = new TableStyle();
					
					//Default
					if (DefaultValues)
					{
						_tablePaneStyle.Width = new Unit("100%");
						_tablePaneStyle.CellPadding = 0;
					}

					if (IsTrackingViewState)
						((IStateManager)_tablePaneStyle).TrackViewState();
				}
				return _tablePaneStyle;
			}
		}


		/// <summary>
		/// The style to be applied to LeftPane.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to LeftPane."),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public TableItemStyle LeftPaneStyle 
		{
			get 
			{
				if (_leftPaneStyle == null) 
				{
					_leftPaneStyle = new TableItemStyle();
					
					//Default
					if (DefaultValues)
					{
						_leftPaneStyle.Width            = new Unit(200);
						_leftPaneStyle.VerticalAlign    = VerticalAlign.Top;
					}

					if (IsTrackingViewState)
						((IStateManager)_leftPaneStyle).TrackViewState();
				}
				return _leftPaneStyle;
			}
		}

		/// <summary>
		/// The style to be applied to RightPane.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to RightPane."),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public TableItemStyle RightPaneStyle 
		{
			get 
			{
				if (_rightPaneStyle == null) 
				{
					_rightPaneStyle = new TableItemStyle();
					
					//Default
					if (DefaultValues)
					{
						_rightPaneStyle.Width = new Unit(200);
						_rightPaneStyle.VerticalAlign = VerticalAlign.Top;
					}

					if (IsTrackingViewState)
						((IStateManager)_rightPaneStyle).TrackViewState();
				}
				return _rightPaneStyle;
			}        
		}

		/// <summary>
		/// The style to be applied to ContentPane.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to ContentPane."),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public TableItemStyle ContentPaneStyle 
		{
			get 
			{
				if (_contentPaneStyle == null) 
				{
					_contentPaneStyle = new TableItemStyle();
					
					//Default
					if (DefaultValues)
					{
						_contentPaneStyle.VerticalAlign = VerticalAlign.Top;
					}

					if (IsTrackingViewState)
						((IStateManager)_contentPaneStyle).TrackViewState();
				}
				return _contentPaneStyle;
			}        
		}  

		/// <summary>
		/// The style to be applied to Horizontal Separator.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to Horizontal Separator"),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public Style HorizontalSeparatorStyle 
		{
			get 
			{
				if (_horizontalSeparatorStyle == null) 
				{
					_horizontalSeparatorStyle = new Style();
					if (IsTrackingViewState)
						((IStateManager)_horizontalSeparatorStyle).TrackViewState();
				}
				return _horizontalSeparatorStyle;
			}
		}
		
		/// <summary>
		/// The style to be applied to Horizontal Separator.
		/// </summary>
		[
		Category("Style"),
		Description("The style to be applied to Vertical Separator."),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
		PersistenceMode(PersistenceMode.InnerProperty)
		]
		public TableItemStyle VerticalSeparatorStyle 
		{
			get 
			{
				if (_verticalSeparatorStyle == null) 
				{
					_verticalSeparatorStyle = new TableItemStyle();
					if (IsTrackingViewState)
						((IStateManager)_verticalSeparatorStyle).TrackViewState();
				}
				return _verticalSeparatorStyle;
			}
		}

		/// <summary>
		/// DataSource triggers loading of modules.
		/// </summary>
		[
		Browsable(false),
		Description("The DataSource.")
		]
		public ArrayList[] DataSource 
		{
			get 
			{
				if (innerDataSource == null) 
				{
					InitializeDataSource();
				}
				return innerDataSource;
			}
		}
		
		/// <summary>
		/// The Left Pane.
		/// </summary>
		[
		Browsable(false),
		DefaultValue(null),
		Description("The Left Pane."),
		PersistenceMode(PersistenceMode.InnerProperty),
		TemplateContainer(typeof(AddonNicePanesTemplate))
		]
		public ITemplate LeftPaneTemplate 
		{
			get 
			{
				return _leftPaneTemplate;
			}
			set 
			{
				_leftPaneTemplate = value;
			}
		}

		/// <summary>
		/// The Content Pane.
		/// </summary>
		[
		Browsable(false),
		DefaultValue(null),
		Description("The Content Pane."),
		PersistenceMode(PersistenceMode.InnerProperty),
		TemplateContainer(typeof(AddonNicePanesTemplate))
		]
		public ITemplate ContentPaneTemplate 
		{
			get 
			{
				return _contentPaneTemplate;
			}
			set 
			{
				_contentPaneTemplate = value;
			}
		}
		
		/// <summary>
		/// The Right Pane.
		/// </summary>
		[
		Browsable(false),
		DefaultValue(null),
		Description("The Right Pane."),
		PersistenceMode(PersistenceMode.InnerProperty),
		TemplateContainer(typeof(AddonNicePanesTemplate))
		]
		public ITemplate RightPaneTemplate 
		{
			get 
			{
				return _rightPaneTemplate;
			}
			set 
			{
				_rightPaneTemplate = value;
			}
		}

		/// <summary>
		/// The HorizontalSeparator.
		/// </summary>
		[
		Browsable(false),
		DefaultValue(null),
		Description("The HorizontalSeparator."),
		PersistenceMode(PersistenceMode.InnerProperty),
		TemplateContainer(typeof(AddonNicePanesTemplate))
		]
		public ITemplate HorizontalSeparatorTemplate 
		{
			get 
			{
				return _horizontalSeparatorTemplate;
			}
			set 
			{
				_horizontalSeparatorTemplate = value;
			}
		}

		/// <summary>
		/// The VerticalSeparator.
		/// </summary>
		[
		Browsable(false),
		DefaultValue(null),
		Description("The VerticalSeparator."),
		PersistenceMode(PersistenceMode.InnerProperty),
		TemplateContainer(typeof(AddonNicePanesTemplate))
		]
		public ITemplate VerticalSeparatorTemplate 
		{
			get 
			{
				return _verticalSeparatorTemplate;
			}
			set 
			{
				_verticalSeparatorTemplate = value;
			}
		}

		/// <summary>
		/// LeftPane
		/// </summary>
		[
		Browsable(false)
		]
		public TableCell LeftPane
		{
			get
			{
				if (_leftPane == null)
				{
					_leftPane       =   new TableCell();
					if (UsePanels)
					{
						Control div =   new HtmlGenericControl(StStr.Div);
						div.ID      =   StStr.leftPane;
						_leftPane.Controls.Add(div);
					}
				}
				return _leftPane;
			}
		}

		/// <summary>
		/// ContentPane
		/// </summary>
		[
		Browsable(false)
		]
		public TableCell ContentPane
		{
			get
			{
				if (_contentPane == null)
				{
					_contentPane = new TableCell();
					if (UsePanels)
					{
						Control div =   new HtmlGenericControl(StStr.Div);
						div.ID      =   StStr.contentPane;
						_contentPane.Controls.Add(div);
					}
				}
				return _contentPane;
			}
		}

		/// <summary>
		/// RightPane
		/// </summary>
		[
		Browsable(false)
		]
		public TableCell RightPane
		{
			get
			{
				if (_rightPane == null)
				{
					_rightPane = new TableCell();
					if (UsePanels)
					{
						Control div =   new HtmlGenericControl(StStr.Div);
						div.ID      =   StStr.rightPane;
						_rightPane.Controls.Add(div);
					}
				}
				return _rightPane;
			}
		}

		public bool HasHorizontalSeparatorTemplate
		{
			get
			{ return ( HorizontalSeparatorTemplate != null ); }
		}

		/// <summary>
		/// Returns a reference to Horizontal separator
		/// </summary>
		protected Control GetHorizontalSeparator()
		{
			_horizontalSeparatorContainer   =   new AddonNicePanesTemplate(this);
			if (HasHorizontalSeparatorTemplate)
				HorizontalSeparatorTemplate.InstantiateIn(_horizontalSeparatorContainer);
			return _horizontalSeparatorContainer;
		}

		public bool HasVerticalSeparatorTemplate
		{
			get
			{ return ( VerticalSeparatorTemplate != null ); }
		}

		/// <summary>
		/// Returns a reference to Vertical separator
		/// </summary>
		protected TableCell GetVerticalSeparator()
		{
			TableCell tc                    =   new TableCell();

			if ( HasVerticalSeparatorTemplate )
			{
				_verticalSeparatorContainer =   new AddonNicePanesTemplate(this);
				VerticalSeparatorTemplate.InstantiateIn(_verticalSeparatorContainer);
				tc.Controls.Add(_verticalSeparatorContainer);
			}
			return tc;		
		}

		#region ViewState 

		/// <summary>
		/// This member overrides Control.LoadViewState
		/// </summary>
		protected override void LoadViewState(object savedState) 
		{
			bool ExistSv        =   ( savedState != null ) ;
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase LoadViewState BEG ExisteSave: {0}.",ExistSv),PanesTraceSwitch.Sw.Info);
			// Customize state management to handle saving state of contained objects.
			if ( ExistSv ) 
			{
				object[] myState = (object[])savedState;

				if (myState[(int)styleIndex.IDX_CONTROL_STYLE] != null)
					base.LoadViewState(myState[(int)styleIndex.IDX_CONTROL_STYLE]);
				if (myState[(int)styleIndex.IDX_TABLE_STYLE] != null)
					((IStateManager)_tablePaneStyle).LoadViewState(myState[(int)styleIndex.IDX_TABLE_STYLE]);
				if (myState[(int)styleIndex.IDX_LEFT_PANE_STYLE] != null)
					((IStateManager)_leftPaneStyle).LoadViewState(myState[(int)styleIndex.IDX_LEFT_PANE_STYLE]);
				if (myState[(int)styleIndex.IDX_CONTENT_PANE_STYLE] != null)
					((IStateManager)_contentPaneStyle).LoadViewState(myState[(int)styleIndex.IDX_CONTENT_PANE_STYLE]);
				if (myState[(int)styleIndex.IDX_RIGHT_PANE_STYLE] != null)
					((IStateManager)_rightPaneStyle).LoadViewState(myState[(int)styleIndex.IDX_RIGHT_PANE_STYLE]);
				if (myState[(int)styleIndex.IDX_HORIZONTAL_SEPARATOR_STYLE] != null)
					((IStateManager)_horizontalSeparatorStyle).LoadViewState(myState[(int)styleIndex.IDX_HORIZONTAL_SEPARATOR_STYLE]);
				if (myState[(int)styleIndex.IDX_VERTICAL_SEPARATOR_STYLE] != null)
					((IStateManager)_verticalSeparatorStyle).LoadViewState(myState[(int)styleIndex.IDX_VERTICAL_SEPARATOR_STYLE]);
			}
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase LoadViewState END.",PanesTraceSwitch.Sw.Info);
		}
		
		/// <summary>
		/// This member overrides Control.SaveViewState
		/// </summary>
		protected override object SaveViewState() 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase SaveViewState BEG.",PanesTraceSwitch.Sw.Info);
			// Customized state management to handle saving state of contained objects  such as styles.
			object baseState                        =   base.SaveViewState();
			object tablePaneStyleState              = (_tablePaneStyle != null) ? ((IStateManager)_tablePaneStyle).SaveViewState() : null;
			object leftPaneStyleState               = (_leftPaneStyle != null) ? ((IStateManager)_leftPaneStyle).SaveViewState() : null;
			object contentPaneStyleState            = (_contentPaneStyle != null) ? ((IStateManager)_contentPaneStyle).SaveViewState() : null;
			object rightPaneStyleState              = (_rightPaneStyle != null) ? ((IStateManager)_rightPaneStyle).SaveViewState() : null;
			object horizontalSeparatorStyleState    = (_horizontalSeparatorStyle != null) ? ((IStateManager)_horizontalSeparatorStyle).SaveViewState() : null;
			object verticalSeparatorStyleState      = (_verticalSeparatorStyle != null) ? ((IStateManager)_verticalSeparatorStyle).SaveViewState() : null;

			object[] myState                                        = new object[7];
			myState[(int)styleIndex.IDX_CONTROL_STYLE]              = baseState;
			myState[(int)styleIndex.IDX_TABLE_STYLE]                = tablePaneStyleState;
			myState[(int)styleIndex.IDX_LEFT_PANE_STYLE]            = leftPaneStyleState;
			myState[(int)styleIndex.IDX_CONTENT_PANE_STYLE]         = contentPaneStyleState;
			myState[(int)styleIndex.IDX_RIGHT_PANE_STYLE]           = rightPaneStyleState;
			myState[(int)styleIndex.IDX_HORIZONTAL_SEPARATOR_STYLE] = horizontalSeparatorStyleState;
			myState[(int)styleIndex.IDX_VERTICAL_SEPARATOR_STYLE]   = verticalSeparatorStyleState;

			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase SaveViewState END.",PanesTraceSwitch.Sw.Info);
			return myState;
		}

		/// <summary>
		/// This member overrides Control.TrackViewState.
		/// </summary>
		protected override void TrackViewState() 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase TrackViewState BEG.",PanesTraceSwitch.Sw.Info);
			// Customized state management to handle saving state of contained objects such as styles.
			base.TrackViewState();

			if (_tablePaneStyle != null)
				((IStateManager)_tablePaneStyle).TrackViewState();
			if (_leftPaneStyle != null)
				((IStateManager)_leftPaneStyle).TrackViewState();
			if (_contentPaneStyle != null)
				((IStateManager)_contentPaneStyle).TrackViewState();
			if (_rightPaneStyle != null)
				((IStateManager)_rightPaneStyle).TrackViewState();
			if (_horizontalSeparatorStyle != null)
				((IStateManager)_horizontalSeparatorStyle).TrackViewState();
			if (_verticalSeparatorStyle != null)
				((IStateManager)_verticalSeparatorStyle).TrackViewState();
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase TrackViewState END.",PanesTraceSwitch.Sw.Info);
		}

		#endregion ViewState 
		#region Controls management

        public AddonNicePanesBase()
        {
            ClientIDMode = System.Web.UI.ClientIDMode.Static;
        }

		/// <summary>
		/// Interface IAddonNicePane : this methods intializes the custom controls in the panes
		/// Called in PreInit Phase to allow setting of skin names before applying them to ADNPage
		/// </summary>
		public virtual void InitPanes(ADNPage pg)
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase InitPanes BEG UsePanels: {0}, ShowFirstHorizontalSeparator: {1}, ShowLastHorizontalSeparator: {2}.",
					UsePanels,ShowFirstHorizontalSeparator,ShowLastHorizontalSeparator),PanesTraceSwitch.Sw.Info);
			Control inserCtl    =   LeftPane;
			if ( UsePanels )
				inserCtl        =   LeftPane.Controls[0]; // div
			bool first          =   true;
			int ctlCount           =   0;
			int ctlTotCount        =   DataSource[IDX_LEFT_PANE_DATA].Count;
			foreach(Control c in DataSource[IDX_LEFT_PANE_DATA])
			{
				if ( first )
				{
					first       =   false;
					if ( ShowFirstHorizontalSeparator )
						inserCtl.Controls.Add(GetHorizontalSeparator());
				}
				inserCtl.Controls.Add(c);
				ctlCount++;
				// No add last separator
				if ( !ShowLastHorizontalSeparator && ( ctlCount == ctlTotCount) )
					continue;
				inserCtl.Controls.Add(GetHorizontalSeparator());
			}

			inserCtl            =   ContentPane;
			if ( UsePanels )
				inserCtl        =   ContentPane.Controls[0]; // div
			first               =   true;
			ctlCount            =   0;
			ctlTotCount         =   DataSource[IDX_CONTENT_PANE_DATA].Count;
			foreach(Control c in DataSource[IDX_CONTENT_PANE_DATA])
			{
				if ( first )
				{
					first       =   false;
					if ( ShowFirstHorizontalSeparator )
						inserCtl.Controls.Add(GetHorizontalSeparator());
				}
				inserCtl.Controls.Add(c);
				ctlCount++;
				// No add last separator
				if ( !ShowLastHorizontalSeparator && ( ctlCount == ctlTotCount) )
					continue;
				inserCtl.Controls.Add(GetHorizontalSeparator());
			}

			inserCtl            =   RightPane;
			if ( UsePanels )
				inserCtl        =   RightPane.Controls[0]; // div
			first               =   true;
			
			ctlCount            =   0;
			ctlTotCount         =   DataSource[IDX_RIGHT_PANE_DATA].Count;

			foreach(Control c in DataSource[IDX_RIGHT_PANE_DATA])
			{
				if ( first )
				{
					first       =   false;
					if ( ShowFirstHorizontalSeparator )
						inserCtl.Controls.Add(GetHorizontalSeparator());
				}
				inserCtl.Controls.Add(c);
				ctlCount++;
				// No add last separator
				if ( !ShowLastHorizontalSeparator && ( ctlCount == ctlTotCount) )
					continue;
				inserCtl.Controls.Add(GetHorizontalSeparator());
			}
			// Install Global pane in Page, must be done before onLoad
			pg.GlobalPane       =   this;
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase InitPanes END.",PanesTraceSwitch.Sw.Info);
		}

		protected override void OnInit(EventArgs e)
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase OnInit BEG.",PanesTraceSwitch.Sw.Info);
			if ( !ChildControlsCreated )
				DataBind();
			base.OnInit(e);
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase OnInit END.",PanesTraceSwitch.Sw.Info);
		}
		/// <summary>
		/// Binds a data source to the invoked server control and all its child controls.
		/// </summary>
		public override void DataBind()
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase DataBind BEG.",PanesTraceSwitch.Sw.Info);
			base.OnDataBinding(EventArgs.Empty);

			// Create the control hierarchy.  First, clear out the child controls
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase DataBind Before Controls.Clear Count: {0}.",Controls.Count),PanesTraceSwitch.Sw.Info);
			Controls.Clear();
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine("[V]AddonNicePanesBase DataBind Before ClearChildViewState.",PanesTraceSwitch.Sw.Info);
			ClearChildViewState();
			// FK4 TrackViewState();

			// Create the control hierarchy
			CreateControlHierarchy(true);

			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase DataBind END.",PanesTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Web server control can set its control style to 
		/// any class that derives from Style by overriding 
		/// the WebControl.CreateControlStyle method
		/// </summary>
		protected override Style CreateControlStyle() 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase CreateControlStyle BEG.",PanesTraceSwitch.Sw.Info);
			// Note that the constructor of Style takes ViewState as an argument. 
			Style style        =   new Style(ViewState);

			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase CreateControlStyle END.",PanesTraceSwitch.Sw.Info);
			return style;
		}

		/// <summary>
		/// Initialize internal data source
		/// </summary>
		protected virtual ArrayList[] InitializeDataSource()
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase InitializeDataSource BEG.",PanesTraceSwitch.Sw.Info);
			innerDataSource                         = new ArrayList[3];
			innerDataSource[IDX_LEFT_PANE_DATA]     = new ArrayList();
			innerDataSource[IDX_CONTENT_PANE_DATA]  = new ArrayList();
			innerDataSource[IDX_RIGHT_PANE_DATA]    = new ArrayList();
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase InitializeDataSource END.",PanesTraceSwitch.Sw.Info);
			return innerDataSource;
		}


		/// <summary>
		/// This member overrides Control.CreateChildControls
		/// </summary>
		protected override void CreateChildControls() 
		{
			bool existVst   =   (ViewState[StStr.PanesCount] != null);
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase CreateChildControls BEG existVst: {0}.",existVst),PanesTraceSwitch.Sw.Info);
//            if ( existVst)
//            {
				// Create the control hierarchy.  First, clear out the child controls
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase CreateChildControls Before Controls.Clear Count: {0}.",Controls.Count),PanesTraceSwitch.Sw.Info);
				// Clear out the control hierachy
				Controls.Clear();
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine("[V]AddonNicePanesBase CreateChildControls Before ClearChildViewState.",PanesTraceSwitch.Sw.Info);
				ClearChildViewState();
				// NK4 TrackViewState();
				CreateControlHierarchy(!existVst);
//            }
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase CreateChildControls END.",PanesTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Apply styles during PreRender phase, so the user can change styles
		/// after calling DataBind the property changes ending up in view state.
		/// </summary>
		protected override void OnPreRender(EventArgs e)
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase OnPreRender BEG IsPostBack: {0}.",Page.IsPostBack),PanesTraceSwitch.Sw.Info);
			try
			{
				if ( !Page.IsPostBack )
					PrepareControlHierarchy();
				base.OnPreRender(e);
			}
			catch(Exception ex)
			{
				if ( PanesTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNicePanesBase OnPreRender ex: {0}", ex),PanesTraceSwitch.Sw.Info);
				throw;
			}
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase OnPreRender END.",PanesTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// render the control hierarchy
		/// </summary>
		protected override void Render(HtmlTextWriter writer) 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase Render BEG.",PanesTraceSwitch.Sw.Info);
			if ( DesignMode )
				EnsureChildControls();
			try
			{
				base.Render(writer);
			}
			catch(Exception ex)
			{
				if ( PanesTraceSwitch.Sw.TraceError )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]AddonNicePanesBase Render ex: {0}", ex),PanesTraceSwitch.Sw.Info);
				throw;
			}
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase Render END.",PanesTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// This member overrides Control.PrepareControlHierarchy
		/// </summary>
		private void PrepareControlHierarchy() 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase PrepareControlHierarchy BEG DynamicPanes: {0}.",DynamicPanes),PanesTraceSwitch.Sw.Info);
			if ( DesignMode )
				return;
			if (!HasControls())
			{
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy no Controls END.", PanesTraceSwitch.Sw.Info);
				return;
			}

			Debug.Assert(Controls[0] is Table);

			PageSettings pgSettings                 =   ((ADNPage)Page).portalSettings.ActivePageSettings;
			Table table                             =   (Table)Controls[0];
			table.MergeStyle(TablePaneStyle);

			Debug.Assert(table.Rows.Count == 1);
			TableCellCollection cells               =   table.Rows[0].Cells;
			Debug.Assert(cells.Count == 7);

			TableCell firstSeparator                =   cells[0];
			firstSeparator.Visible                  =   ShowFirstSeparator;
			firstSeparator.MergeStyle(VerticalSeparatorStyle);

			TableCell leftCell                      =   cells[1];
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase PrepareControlHierarchy LeftPane Controls.Count: {0}.",LeftPane.Controls.Count),PanesTraceSwitch.Sw.Info);
			int wdt                                 =   pgSettings.Width[0];
			if (wdt != 0)
			{
				if (wdt > 0)
						LeftPaneStyle.Width         =   new Unit(wdt, UnitType.Pixel);
				else    LeftPaneStyle.Width         =   new Unit(-wdt, UnitType.Percentage);
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase PrepareControlHierarchy force LeftPane width: {0}.",LeftPaneStyle.Width),PanesTraceSwitch.Sw.Info);
			}
			leftCell.MergeStyle(LeftPaneStyle);

			TableCell leftToContentSeparator            =   cells[2];
			leftToContentSeparator.MergeStyle(VerticalSeparatorStyle);

			if (DynamicPanes)
			{
				if ( leftToContentSeparator.HasControls()
					|| leftToContentSeparator.Text.Trim() != String.Empty)
				{
					leftToContentSeparator.Visible      =   true;
				}
				else
				{
					leftToContentSeparator.Visible      =   false;
					if ( PanesTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy leftToContentSeparator hidden.",PanesTraceSwitch.Sw.Info);
				}

				if (!UsePanels)
				{
					if (LeftPane.HasControls()
						|| LeftPane.Text.Trim() != String.Empty)
					{
						LeftPane.Visible                =   true;
					}
					else
					{
						LeftPane.Visible                =   false;
						leftToContentSeparator.Visible = false; // avoid double vert sep if showfirst true
						if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy LeftPane hidden.",PanesTraceSwitch.Sw.Info);
					}
				}
				else
				{
					if (LeftPane.Controls[0].HasControls()
						|| ((HtmlGenericControl)LeftPane.Controls[0]).InnerText.Trim() != String.Empty)
					{
						LeftPane.Visible                =   true;
					}
					else
					{
						LeftPane.Visible                =   false;
						leftToContentSeparator.Visible  =   false; // avoid double vert sep if showfirst true
						 if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy LeftPane hidden.",PanesTraceSwitch.Sw.Info);
				   }
				}
			}

			TableCell contentCell                       =   cells[3];
			wdt                                         =   pgSettings.Width[1];
			if ( wdt != 0 )
			{
				if ( wdt > 0 )
						ContentPaneStyle.Width          =   new Unit(wdt, UnitType.Pixel);
				else    ContentPaneStyle.Width          =   new Unit(-wdt, UnitType.Percentage);
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase PrepareControlHierarchy force ContentPane width: {0}.",ContentPaneStyle.Width),PanesTraceSwitch.Sw.Info);
			}
			// Content merging delayed until we know if right cell visible

			TableCell contentToRightSeparator           =   cells[4];
			contentToRightSeparator.MergeStyle(VerticalSeparatorStyle);

			TableCell rightCell                         =   cells[5];
			wdt                                         =   pgSettings.Width[2];
			if (wdt != 0)
			{
				if (wdt > 0)
						RightPaneStyle.Width            =   new Unit(wdt, UnitType.Pixel);
				else    RightPaneStyle.Width            =   new Unit(-wdt, UnitType.Percentage);
				if ( PanesTraceSwitch.Sw.TraceVerbose )
					Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase PrepareControlHierarchy force RightPane width: {0}.",RightPaneStyle.Width),PanesTraceSwitch.Sw.Info);
			}
			rightCell.MergeStyle(RightPaneStyle);

			TableCell lastSeparator                     =   cells[6];
			lastSeparator.Visible                       =   ShowLastSeparator;
			lastSeparator.MergeStyle(VerticalSeparatorStyle);
			if (DynamicPanes)
			{
				if (contentToRightSeparator.HasControls() || contentToRightSeparator.Text.Trim() != String.Empty)
				{
					contentToRightSeparator.Visible     =   true;
				}
				else
				{
					contentToRightSeparator.Visible     =   false;
					if ( PanesTraceSwitch.Sw.TraceVerbose )
						Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy contentToRightSeparator hidden.",PanesTraceSwitch.Sw.Info);
				}
				if (!UsePanels)
				{
					if (RightPane.HasControls() || RightPane.Text.Trim() != String.Empty)
					{
						RightPane.Visible               =   true;
					}
					else
					{
						RightPane.Visible               =   false;
						if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy RightPane hidden.",PanesTraceSwitch.Sw.Info);
						lastSeparator.Visible           =   false;
						if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy lastSeparator hidden.",PanesTraceSwitch.Sw.Info);
					}
				}
				else
				{
					if (RightPane.Controls[0].HasControls()
						|| ((HtmlGenericControl)RightPane.Controls[0]).InnerText.Trim() != String.Empty)
					{
						RightPane.Visible               =   true;
					}
					else
					{
						RightPane.Visible               =   false;
						if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy RightPane hidden.",PanesTraceSwitch.Sw.Info);
						lastSeparator.Visible           =   false;
						if ( PanesTraceSwitch.Sw.TraceVerbose )
							Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy lastSeparator hidden.",PanesTraceSwitch.Sw.Info);
					}
				}
			}
			// We delayed this operation to wait all visibilities being set
			if ( !leftCell.Visible && !rightCell.Visible )
				ContentPaneStyle.CssClass               =   string.Format("{0} {1}",ContentPaneStyle.CssClass,"NoLeftRightPane");
			else if ( !leftCell.Visible )
				ContentPaneStyle.CssClass               =   string.Format("{0} {1}",ContentPaneStyle.CssClass,"NoLeftPane");
			else if ( !rightCell.Visible )
				ContentPaneStyle.CssClass               =   string.Format("{0} {1}",ContentPaneStyle.CssClass,"NoRightPane");
			else ContentPaneStyle.CssClass               =   string.Format("{0} {1}",ContentPaneStyle.CssClass,"AllPanes");
			contentCell.MergeStyle(ContentPaneStyle);
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase PrepareControlHierarchy END.",PanesTraceSwitch.Sw.Info);
		}

		/// <summary>
		/// Create a table containing 3 panes in one row
		/// </summary>
		private void CreateControlHierarchy(bool useDataSource) 
		{
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]AddonNicePanesBase CreateControlHierarchy BEG useDataSource: {0}.",useDataSource),PanesTraceSwitch.Sw.Info);
			Table table                         =   new Table();
			table.ID                            =   string.Format("TablePane_{0}",ClientID);
			Controls.Add(table);

			TableRow contentRow                 =   new TableRow();

			contentRow.Controls.Add(GetVerticalSeparator());

			contentRow.Controls.Add(LeftPane);
			TableCell leftToContentSeparator    =   GetVerticalSeparator();
			contentRow.Controls.Add(leftToContentSeparator);

			Control inserCtl                    =   LeftPane;
			if ( UsePanels )
				inserCtl                        =   LeftPane.Controls[0]; // div
			if (LeftPaneTemplate != null)
			{
				_leftPaneContainer              =   new AddonNicePanesTemplate(this);
				LeftPaneTemplate.InstantiateIn(_leftPaneContainer);
				inserCtl.Controls.AddAt(0, _leftPaneContainer);
			}

			contentRow.Controls.Add(ContentPane);
			
			inserCtl                            =   ContentPane;
			if ( UsePanels )
				inserCtl                        =   ContentPane.Controls[0]; // div
			if (ContentPaneTemplate != null)
			{
				_contentPaneContainer           =   new AddonNicePanesTemplate(this);
				ContentPaneTemplate.InstantiateIn(_contentPaneContainer);
				inserCtl.Controls.AddAt(0, _contentPaneContainer);
			}
			
			TableCell contentToRightSeparator   =   GetVerticalSeparator();
			contentRow.Controls.Add(contentToRightSeparator);
			contentRow.Controls.Add(RightPane);

			inserCtl                            =   RightPane;
			if ( UsePanels )
				inserCtl                        =   RightPane.Controls[0]; // div
			if (RightPaneTemplate != null)
			{
				_rightPaneContainer             =   new AddonNicePanesTemplate(this);
				RightPaneTemplate.InstantiateIn(_rightPaneContainer);
				inserCtl.Controls.AddAt(0, _rightPaneContainer);
			}

			contentRow.Controls.Add(GetVerticalSeparator());
			
			table.Controls.Add(contentRow);
			if ( useDataSource )
				ViewState[StStr.PanesCount]     =   contentRow.Controls.Count;
			ChildControlsCreated                =   true;
			if ( PanesTraceSwitch.Sw.TraceVerbose )
				Trace2.WriteLine( "[V]AddonNicePanesBase CreateControlHierarchy END.",PanesTraceSwitch.Sw.Info);
		}    
		#endregion Controls management
	}
}